#include "Node.h"
#include <assert.h>

Node::Node(void)
: mRot(NULL)
, mScale(NULL)
, tag(INVALID_TAG)
, children(NULL)
, parent(NULL)
, bDraw(true)
{
}

Node::~Node(void)
{
	DELETE_PTR(mRot);
	DELETE_PTR(mScale);
}

bool Node::Init(void)
{
	return true;
}

void Node::Draw(void) 
{
}

void Node::Update(float delta)
{
}

void Node::DrawChildren(void)
{
	glPushMatrix();

		if(mRot && *mRot != vec3(0,0,0))
		{
			glRotatef(mRot->x,1,0,0);
			glRotatef(mRot->y,0,1,0);
			glRotatef(mRot->z,0,0,1);
		}

		if(mScale) glScalef(mScale->x,mScale->y,mScale->z);
	
		if(parent)
		{
			vec3 t = wPos - parent->wPos;
			glTranslatef(t.x, t.y, t.z);
		}

		if(bDraw) Draw();

		if(!children) { glPopMatrix(); return; }

		for(ListIter it = children->begin(); it != children->end(); it++)
		{
			if(*it)
			{ 
				(*it)->DrawChildren();
			}
		}

	glPopMatrix();
}

void Node::UpdateChildren(float delta)
{
	if(!children) return;
	for(ListIter it = children->begin(); it != children->end(); it++)
	{
		if(*it)
		{ 
			(*it)->Update(delta);
			(*it)->UpdateChildren(delta);
		}
	}
}

void Node::AddChild(Node *child)
{
	// We don't want them null pointers y'all
	ErrorMsg(!child,"Invalid child pointer");
	ErrorMsg(child->parent, "Node already has a parent");

	if(!children) children = new list<Node*>;

	// Girl needs a little identifier
	child->SetTag( children->size() );

	// Push her in em list
	children->push_back(child);

	child->wPos += wPos;

	// Babe needs to know her parents
	child->SetParent(this);
}

Node* Node::GetChild(int tag)
{
	ErrorMsgReturn(tag == INVALID_TAG,"Invalid tag number",NULL);
	ErrorMsgReturn(!children,"Node has no children",NULL);

	Node* child = NULL;
	ListIter i;

	for(i = children->begin(); i != children->end(); ++i)
	{
		if( tag == (*i)->GetTag() )
			child = *i;
	}

	ErrorMsgReturn(!child,"Child not found", NULL);
}

list<Node*>* Node::GetChildren(void)
{
	return children;
}

int Node::GetChildrenCount(void)
{
	return (children) ? children->size() : 0;
}

void Node::RemoveChild(Node* child)
{
	ErrorMsg(!child,"Invalid child pointer");
	ErrorMsg(!children,"Node has no children");

	children->remove(child);
}

void Node::RemoveChildbyTag(int tag)
{
	ErrorMsg(tag == INVALID_TAG,"Invalid tag number");
	ErrorMsg(!children,"Node has no children");

	Node* child = GetChild(tag);
	RemoveChild(child);
}

void Node::SetParent(Node *Parent)
{
	ErrorMsg(!Parent,"Invalid parent pointer");

	// Remove this child from the old parent's list
	if(parent) parent->RemoveChild(this);

	parent = Parent;
}

Node* Node::GetParent(void)
{
	// <dadjoke> Node is Batman </dadjoke>
	ErrorMsgReturn(!parent,"Node has no parent",NULL);

	return parent;
}

void Node::SetTag(int Tag)
{
	tag = Tag;
}

int Node::GetTag(void)
{
	return tag;
}

void Node::Translate(float x, float y, float z)
{
	wPos += vec3(x,y,z);
	if(children)
		for(ListIter i = children->begin(); i != children->end(); ++i)
			(*i)->Translate(x,y,z);
}

void Node::Translate(vec3 v)
{
	Translate(v.x, v.y, v.z);
}

void Node::Rotate(float angle, float x, float y, float z)
{
	if(mRot == NULL) mRot = new vec3;
	if(x) mRot->x += angle * x;
	if(y) mRot->y += angle * y;
	if(z) mRot->z += angle * z;
}

void Node::Rotate(float angle, vec3 v)
{
	Rotate(angle, v.x, v.y, v.z);
}

void Node::Scale(float x, float y, float z)
{
	if(mScale == NULL) mScale = new vec3(1,1,1);
	mScale->operator()(x,y,z);
}

void Node::Scale(vec3 v)
{
	Scale(v.x, v.y, v.z);
}

vec3 Node::getWorldPos(void)
{
	return wPos;
}

void Node::setWorldPos(vec3 v)
{
	wPos = v;
}

vec3 Node::getRelativePos(void)
{
	// <dadjoke> Node is Batman </dadjoke>
	ErrorMsgReturn(!parent,"Node has no parent", vec3());

	return wPos - parent->getWorldPos();
}

vec3 Node::getRotation(void)
{
	return (mRot) ? *mScale : vec3(0,0,0);
}

vec3 Node::getScale(void)
{
	return (mScale) ? *mScale : vec3(1,1,1);
}